import struct, binascii
import random

from bitstring import BitArray

from jt808log import log


#获取数据的commandId
def get_commandId(data):

	# 去掉原始数据头标识
	content = data[1:-1]
	commandId = struct.unpack('>H', content[:2])[0]	#十进制
	commandId = '%04x' % commandId 	#十六进制

	return commandId


#根据 十进制<commandId> 获取对应的类,返回 类的实例
#msg_ins = getclass(256)
def getMsgClass(commandId):
	if commandId in MSGS:
		return MSGS[commandId]()
	else:
		return


#消息类 Message
class Message(object):

	commandId = None
	# seqNum = 0
	baocount = 1
	baoid = 1
	fenbaoLen = 1000 #最大值1023
	#编码属性
	flagBit =  struct.pack('>B',0x7e)
	# termPhone = ''
	structParams = []

	def __init__(self, termPhone=None, seqNum=0, **kwargs):

		self.body_Length = 0
		self.seqNum = seqNum
		self.termPhone = termPhone

		for key, value in kwargs.items():
			setattr(self, key, value)

		for sParam in self.structParams:
			setattr(self, sParam[0], sParam[2])


	# 类实例属性编码成 Raw
	def generateData(self):
		
		rst = []
		body = b''
		reps_ins = self.requireAck()

		# structParams = [('Seq','>H',0), ('MsgID','>H',0), ('Result','>B',0)]
		for dParams in reps_ins.structParams:
			# print(getattr(reps_ins, dParams[0]))
			fmt = dParams[1]
			if dParams[0] == 'Auth':
				body = body + struct.pack(fmt, *make_auth())
				print(getattr(reps_ins, dParams[0]))
				continue
		
			body = body + struct.pack( fmt, getattr(reps_ins, dParams[0]) )
		
		jiami = 0 
		fenbao = 0
		baocount = 1

		bodylen = self.fenbaoLen
		msgprop = struct.pack('>H', BitArray('0b00%s00%s, uint:10=%s' % (fenbao,jiami,bodylen)).uint)
		bcd_sim = struct.pack('>6B', *str_packed_bcd(self.termPhone))
		header = struct.pack('>H', reps_ins.commandId) + msgprop + bcd_sim + struct.pack('>H', self.seqNum)
		msgbody = body
		check = check_code(header + msgbody)

		rst.append(self.flagBit + header + msgbody + check + self.flagBit)
		return rst[0]


	# 接收 Raw数据解析成类实例属性
	@staticmethod
	def pasrseMsg(data=None):
		dlen = len(data)
		if dlen > 0:
			commandId = get_commandId(data)	#十六进制数字
		else:
			commandId = 0x8100
			
		pos = 0
		dataLen = len(data)
		content = data[1:dataLen-1]
		msg_ins = getMsgClass(commandId)

		if msg_ins:

			''' 1 消息头信息解析'''
			# 无分包时 消息头长度 12Bytes
			pos = 12	
			
			# 消息体属性 解析
			msg_ins.msgProp = struct.unpack('>H', content[2:4])[0]
			msg_ins.msgProp_bitArray = BitArray('uint:16=%s' % msg_ins.msgProp).bin
			msg_ins.msgProp_subPackage = int(msg_ins.msgProp_bitArray[2:3])
			msg_ins.msgProp_encrypt = int(msg_ins.msgProp_bitArray[5:6])
			msg_ins.msgProp_bodyLength = int(msg_ins.msgProp_bitArray[7:], 2)
			log.info('subPackage: %d, encrypt: %d, Length: %d' % (msg_ins.msgProp_subPackage, msg_ins.msgProp_encrypt, msg_ins.msgProp_bodyLength))
			
			# 手机号 解析
			msg_ins.termPhone_tuple = struct.unpack('>6B', content[4:10])
			msg_ins.termPhone = bcd_unpack_str(msg_ins.termPhone_tuple)
			log.info('Sim: %s' % msg_ins.termPhone)
			
			# 消息流水号 解析
			msg_ins.seq = int(struct.unpack('>H', content[10:12])[0])
			log.info('seq: %s' % msg_ins.seq)

			# 消息体属性 若分包 解析分包数、分包id 
			if  msg_ins.msgProp_subPackage:
				pos = 16
				msg_ins.msg_Package_totle, msg_ins.msg_Package_id = struct.unpack('>2H', content[12:16])
				log.info('Package: totle %d, id %d' % (msg_ins.msg_Package_totle, msg_ins.msg_Package_id))
			

			''' 2 消息体内容解析'''
			# structParams = [('Seq','>H',0), ('MsgID','>H',0), ('Result','>B',0)]
			for sParam in msg_ins.structParams:
				fmt = sParam[1]

				# BCD
				if type(sParam[2] == 'BCD'):
					s_len = struct.calcsize(fmt)
					tmp_data = content[pos: pos+s_len]
					setattr( msg_ins, sParam[0], bcd_unpack_str(struct.unpack(fmt, tmp_data)) )		#????
					pos += s_len
					continue

				# strings
				if type(sParam[2]) == str:
					str_len = struct.calcsize(fmt)
					tmp_data = content[pos: pos+str_len]
					# log.info('tmp_data: %s' % str(tmp_data))
					setattr(msg_ins, sParam[0], tmp_data[0:8])	#??? 截取的是终端ID
					pos += str_len
					continue

				setattr( msg_ins, sParam[0], struct.unpack(fmt, content[pos:pos+struct.calcsize(fmt)])[0])
				pos += struct.calcsize(fmt)

			# 接收的数据 保存为类实例属性返回 
			return msg_ins


	def __repr__(self):
		##
		r = "Message--commandId:%04x--seq:%s--" % (self.commandId, self.seq)
		for sParam in self.structParams:
			if sParam[2] == 'r':
				r += "%s:%r--" % (sParam[0], getattr(self, sParam[0], 0))
			elif sParam[0] == 'MsgID':
				r += "%s:%x--" % (sParam[0], getattr(self, sParam[0], 0))
			else:
				tmpdata = getattr(self, sParam[0], 0)
				r += "%s:%s--" % (sParam[0], tmpdata )

		return r
